﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace iNet.Media
{
	/// <summary>
	/// 無特定內部格式的中繼資料。
	/// </summary>
	public class GenericMetadata : MetadataBase
	{
		#region 欄位
		readonly Dictionary<string, object> _Properties = new Dictionary<string, object>();
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 GenericMetadata 執行個體。
		/// </summary>
		public GenericMetadata()
		{ }
		/// <summary>
		/// 初始化新的 GenericMetadata 執行個體。
		/// </summary>
		/// <param name="template">範本中繼資料。</param>
		/// <param name="isReadOnly">是否為唯讀。</param>
		public GenericMetadata(IMetadata template, bool isReadOnly)
			: base(template, isReadOnly)
		{ }
		#endregion
		#region Authors
		/// <summary>
		/// 取得或設定媒體的作者。
		/// </summary>
		public override string[] Authors
		{
			get
			{
				return this.GetProperty<string[]>("Authors");
			}
			set
			{
				this.SetProperty("Authors", value);
			}
		}
		#endregion
		#region City
		/// <summary>
		/// 取得或設定媒體內容所在的城市。
		/// </summary>
		public override string City
		{
			get
			{
				return this.GetProperty<string>("City");
			}
			set
			{
				this.SetProperty("City", value);
			}
		}
		#endregion
		#region Clone
		/// <summary>
		/// 建立可修改的 GenericMetadata 副本。
		/// </summary>
		/// <returns>GenericMetadata 副本。</returns>
		public override object Clone()
		{
			return new GenericMetadata(this, false);
		}
		#endregion
		#region Comment
		/// <summary>
		/// 取得或設定媒體的註解文字。
		/// </summary>
		public override string Comment
		{
			get
			{
				return this.GetProperty<string>("Comment");
			}
			set
			{
				this.SetProperty("Comment", value);
			}
		}
		#endregion
		#region CopyFrom
		/// <summary>
		/// 從指定的中繼資料複製屬性。
		/// </summary>
		/// <param name="metadata">指定的中繼資料。</param>
		/// <exception cref="InvalidOperationException">中繼資料為唯讀。</exception>
		public override void CopyFrom(IMetadata metadata)
		{
			//確認狀態
			if (this.IsReadOnly)
				throw new InvalidOperationException();

			//複製
			if (metadata != null && metadata != this)
			{
				this.Authors = metadata.Authors;
				this.City = metadata.City;
				this.Comment = metadata.Comment;
				this.CountryRegion = metadata.CountryRegion;
				this.Copyright = metadata.Copyright;
				this.CreationTime = metadata.CreationTime;
				this.Keywords = metadata.Keywords;
				this.LastWriteTime = metadata.LastWriteTime;
				this.Rating = metadata.Rating;
				this.RatingPercentage = metadata.RatingPercentage;
				this.Software = metadata.Software;
				this.StateProvince = metadata.StateProvince;
				this.Subject = metadata.Subject;
				this.Title = metadata.Title;
			}
		}
		#endregion
		#region Copyright
		/// <summary>
		/// 取得或設定媒體的版權資訊。
		/// </summary>
		public override string Copyright
		{
			get
			{
				return this.GetProperty<string>("Copyright");
			}
			set
			{
				this.SetProperty("Copyright", value);
			}
		}
		#endregion
		#region CountryRegion
		/// <summary>
		/// 取得或設定媒體內容所在的國家或地區。
		/// </summary>
		public override string CountryRegion
		{
			get
			{
				return this.GetProperty<string>("CountryRegion");
			}
			set
			{
				this.SetProperty("CountryRegion", value);
			}
		}
		#endregion
		#region CreationTime
		/// <summary>
		/// 取得或設定媒體建立時間。
		/// </summary>
		public override DateTime? CreationTime
		{
			get
			{
				return this.GetProperty<DateTime?>("CreationTime");
			}
			set
			{
				this.SetProperty("CreationTime", value);
			}
		}
		#endregion
		#region GetAsReadOnly
		/// <summary>
		/// 取得唯讀的 GenericMetadata。
		/// </summary>
		/// <returns>唯讀的 GenericMetadata。</returns>
		public override IMetadata GetAsReadOnly()
		{
			if (this.IsReadOnly)
				return this;
			return new GenericMetadata(this, true);
		}
		#endregion
		#region GetProperty
		/// <summary>
		/// 取得指定名稱的屬性值。
		/// </summary>
		/// <typeparam name="T">屬性值型別。</typeparam>
		/// <param name="name">屬性名稱。</param>
		/// <returns>指定名稱的屬性值。若屬性不存在或無法轉換成指定型別，將傳回型別預設值。</returns>
		/// <exception cref="ArgumentNullException">name 為 Null (Visual Basic 為 Nothing)。</exception>
		protected T GetProperty<T>(string name)
		{
			//確認參數
			if (name == null)
				throw new ArgumentNullException("name");

			//取得屬性
			object value;
			if (_Properties.TryGetValue(name, out value))
			{
				//直接回傳
				if (value is T)
					return (T)value;

				//轉換型別
				T convertedValue;
				if (value.TryCast<T>(out convertedValue))
					return convertedValue;
			}
			return default(T);
		}
		#endregion
		#region Keywords
		/// <summary>
		/// 取得或設定媒體的關鍵字。
		/// </summary>
		public override string[] Keywords
		{
			get
			{
				return this.GetProperty<string[]>("Keywords");
			}
			set
			{
				this.SetProperty("Keywords", value);
			}
		}
		#endregion
		#region LastWriteTime
		/// <summary>
		/// 取得或設定媒體最近更新時間。
		/// </summary>
		public override DateTime? LastWriteTime
		{
			get
			{
				return this.GetProperty<DateTime?>("LastWriteTime");
			}
			set
			{
				this.SetProperty("LastWriteTime", value);
			}
		}
		#endregion
		#region Rating
		/// <summary>
		/// 取得或設定媒體的評價。
		/// </summary>
		public override int? Rating
		{
			get
			{
				return this.GetProperty<int?>("Rating");
			}
			set
			{
				this.SetProperty("Rating", value);
			}
		}
		#endregion
		#region RatingPercentage
		/// <summary>
		/// 取得或設定媒體的評價百分比。
		/// </summary>
		public override int? RatingPercentage
		{
			get
			{
				return this.GetProperty<int?>("RatingPercentage");
			}
			set
			{
				this.SetProperty("RatingPercentage", value);
			}
		}
		#endregion
		#region SetProperty
		/// <summary>
		/// 設定指定名稱的屬性值。
		/// </summary>
		/// <param name="name">屬性名稱。</param>
		/// <param name="value">新的屬性值。</param>
		/// <exception cref="ArgumentNullException">name 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="InvalidOperationException">中繼資料為唯讀。</exception>
		protected void SetProperty(string name, object value)
		{
			//確認參數
			if (name == null)
				throw new ArgumentNullException("name");

			//確認狀態
			if (this.IsReadOnly)
				throw new InvalidOperationException();

			//更新屬性值
			_Properties[name] = value;
		}
		#endregion
		#region Software
		/// <summary>
		/// 取得或設定製作媒體的軟體名稱。
		/// </summary>
		public override string Software
		{
			get
			{
				return this.GetProperty<string>("Software");
			}
			set
			{
				this.SetProperty("Software", value);
			}
		}
		#endregion
		#region StateProvince
		/// <summary>
		/// 取得或設定媒體內容所在的省或州。
		/// </summary>
		public override string StateProvince
		{
			get
			{
				return this.GetProperty<string>("StateProvince");
			}
			set
			{
				this.SetProperty("StateProvince", value);
			}
		}
		#endregion
		#region Subject
		/// <summary>
		/// 取得或設定媒體的主旨。
		/// </summary>
		public override string Subject
		{
			get
			{
				return this.GetProperty<string>("Subject");
			}
			set
			{
				this.SetProperty("Subject", value);
			}
		}
		#endregion
		#region Title
		/// <summary>
		/// 取得或設定媒體的標題。
		/// </summary>
		public override string Title
		{
			get
			{
				return this.GetProperty<string>("Title");
			}
			set
			{
				this.SetProperty("Title", value);
			}
		}
		#endregion
	}
}
